{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 通过净利润的思想来挑选股票"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import pandas as pd\n",
    "import numpy as np\n",
    "import pdb\n",
    "import time\n",
    "\n",
    "import datetime\n",
    "\n",
    "import sys\n",
    "sys.path.append(\"../utils/\")\n",
    "import token_util\n",
    "pro = token_util.set_token()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "*获取股票列表*"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "stock_list.shape:  (542, 5)\n",
      "\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>ts_code</th>\n",
       "      <th>name</th>\n",
       "      <th>total_mv</th>\n",
       "      <th>pe_ttm</th>\n",
       "      <th>price</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>000021.SZ</td>\n",
       "      <td>深科技</td>\n",
       "      <td>2.740956e+06</td>\n",
       "      <td>77.8015</td>\n",
       "      <td>18.840</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>000025.SZ</td>\n",
       "      <td>特力A</td>\n",
       "      <td>7.504725e+05</td>\n",
       "      <td>36.2790</td>\n",
       "      <td>17.485</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>000028.SZ</td>\n",
       "      <td>国药一致</td>\n",
       "      <td>1.743333e+06</td>\n",
       "      <td>14.2903</td>\n",
       "      <td>40.705</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>000032.SZ</td>\n",
       "      <td>深桑达A</td>\n",
       "      <td>7.355310e+05</td>\n",
       "      <td>59.1230</td>\n",
       "      <td>17.985</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>000034.SZ</td>\n",
       "      <td>神州数码</td>\n",
       "      <td>1.498475e+06</td>\n",
       "      <td>21.3637</td>\n",
       "      <td>23.190</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "     ts_code  name      total_mv   pe_ttm   price\n",
       "0  000021.SZ   深科技  2.740956e+06  77.8015  18.840\n",
       "1  000025.SZ   特力A  7.504725e+05  36.2790  17.485\n",
       "2  000028.SZ  国药一致  1.743333e+06  14.2903  40.705\n",
       "3  000032.SZ  深桑达A  7.355310e+05  59.1230  17.985\n",
       "4  000034.SZ  神州数码  1.498475e+06  21.3637  23.190"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "stock_list = pd.read_csv(\"../data_pulled/stock_date_delta_price(10, 200).csv\")\n",
    "print(\"stock_list.shape: \", stock_list.shape)\n",
    "print(\"\")\n",
    "stock_list.head()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 成长股\n",
    "三年内年净利润增长率最少大于10%，平均大于25% <br>\n",
    "毛利率三年平均>40% <br>\n",
    "净利率三年平均>20% <br>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "*获取数据*"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "def get_data(ts_code, time_list):\n",
    "    for i in range(len(time_list)):\n",
    "\n",
    "        ret = pro.income(ts_code=ts_code, period='20'+str(time_list[i])+'1231', fields='ts_code,end_date,n_income,\\\n",
    "                         revenue,oper_cost')\n",
    "        rets = pd.concat([rets, ret], ignore_index=True) if i != 0 else ret\n",
    "\n",
    "    rets = rets.drop_duplicates()[-4:].reset_index(drop=True)\n",
    "    rets['mao_li'] = (rets['revenue']-rets['oper_cost'])/rets['revenue']\n",
    "    rets['jing_li'] = rets['n_income']/rets['revenue']\n",
    "    \n",
    "    return rets.drop(['oper_cost', 'revenue'], axis=1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "*进行筛选*"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "task accomplish: 0.05 %, cost time : 4.22 minutes\n",
      "task accomplish: 0.1 %, cost time : 8.72 minutes\n",
      "task accomplish: 0.15 %, cost time : 13.38 minutes\n",
      "task accomplish: 0.21 %, cost time : 17.62 minutes\n",
      "task accomplish: 0.26 %, cost time : 22.18 minutes\n",
      "task accomplish: 0.31 %, cost time : 26.77 minutes\n",
      "task accomplish: 0.36 %, cost time : 31.43 minutes\n",
      "task accomplish: 0.41 %, cost time : 35.97 minutes\n",
      "task accomplish: 0.46 %, cost time : 40.15 minutes\n",
      "task accomplish: 0.51 %, cost time : 44.8 minutes\n",
      "task accomplish: 0.57 %, cost time : 49.28 minutes\n",
      "task accomplish: 0.62 %, cost time : 53.5 minutes\n",
      "task accomplish: 0.67 %, cost time : 58.22 minutes\n",
      "task accomplish: 0.72 %, cost time : 62.62 minutes\n",
      "task accomplish: 0.77 %, cost time : 66.82 minutes\n",
      "task accomplish: 0.82 %, cost time : 71.57 minutes\n",
      "task accomplish: 0.87 %, cost time : 75.92 minutes\n",
      "task accomplish: 0.93 %, cost time : 80.17 minutes\n",
      "task accomplish: 0.98 %, cost time : 84.93 minutes\n",
      "finish task !! total time : 86.95 minutes\n"
     ]
    }
   ],
   "source": [
    "candidate_list = []\n",
    "time_list = [15, 16, 17, 18, 19, 20]\n",
    "times = 0\n",
    "starttime = datetime.datetime.now()\n",
    "len_stock = len(stock_list)\n",
    "\n",
    "while True:\n",
    "    \n",
    "    # 发生中断后，防止遗漏\n",
    "    start_index = 0\n",
    "    \n",
    "    for cur_index in range(start_index, len_stock):\n",
    "        \n",
    "        start_index = cur_index\n",
    "        \n",
    "        try:\n",
    "            data = get_data(stock_list[\"ts_code\"][cur_index], time_list)\n",
    "        except:\n",
    "            time.sleep(5)\n",
    "\n",
    "        times += 1\n",
    "        pass_data = True\n",
    "        in_come_list = []\n",
    "\n",
    "        maoli_mean = data['mao_li'][1:].mean()\n",
    "        jingli_mean = data['jing_li'][1:].mean()\n",
    "\n",
    "        if maoli_mean >= 0.4 and jingli_mean >= 0.2:\n",
    "\n",
    "            for i in range(1, len(data)):\n",
    "                n_income_last = data.iloc[i-1][\"n_income\"]\n",
    "                n_income_cur = data.iloc[i][\"n_income\"]\n",
    "                income_rate = (n_income_cur - n_income_last) / n_income_last\n",
    "                in_come_list.append(income_rate)\n",
    "\n",
    "                if n_income_cur > 0 and n_income_cur > n_income_last and income_rate >= 0.10:\n",
    "                    continue\n",
    "                else:\n",
    "                    pass_data = False\n",
    "                    break\n",
    "        else:\n",
    "            pass_data = False\n",
    "        \n",
    "        if len(in_come_list) == 3 and pass_data is True and np.mean(in_come_list) >= 0.25:\n",
    "            candidate_list.append(stock_list[\"ts_code\"][cur_index])\n",
    "            \n",
    "        if cur_index != 0 and cur_index % 100 == 0:\n",
    "            endtime = datetime.datetime.now()\n",
    "            print(\"task accomplish: {} %, cost time : {} minutes\".format(round((cur_index+1)/len_stock, 2), \\\n",
    "                                            round((endtime - starttime).seconds / 60, 2)))\n",
    "            \n",
    "    if cur_index >= len_stock - 1:\n",
    "        endtime = datetime.datetime.now()\n",
    "        print(\"finish task !! total time : {} minutes\".format(round((endtime - starttime).seconds / 60, 2)))\n",
    "        break"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "31"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "len(candidate_list)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['000568.SZ',\n",
       " '002034.SZ',\n",
       " '002099.SZ',\n",
       " '002127.SZ',\n",
       " '002439.SZ',\n",
       " '002677.SZ',\n",
       " '002821.SZ',\n",
       " '002822.SZ',\n",
       " '002823.SZ',\n",
       " '002825.SZ',\n",
       " '002826.SZ',\n",
       " '002827.SZ',\n",
       " '002828.SZ',\n",
       " '002830.SZ',\n",
       " '002831.SZ',\n",
       " '002832.SZ',\n",
       " '002833.SZ',\n",
       " '002901.SZ',\n",
       " '600276.SH',\n",
       " '600436.SH',\n",
       " '600519.SH',\n",
       " '600779.SH',\n",
       " '603338.SH',\n",
       " '603387.SH',\n",
       " '603393.SH',\n",
       " '603429.SH',\n",
       " '603583.SH',\n",
       " '603589.SH',\n",
       " '603638.SH',\n",
       " '603658.SH',\n",
       " '603688.SH']"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "candidate_list"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>ts_code</th>\n",
       "      <th>name</th>\n",
       "      <th>pe_ttm</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>1945</th>\n",
       "      <td>603999.SH</td>\n",
       "      <td>读者传媒</td>\n",
       "      <td>48.0831</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "        ts_code  name   pe_ttm\n",
       "1945  603999.SH  读者传媒  48.0831"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "stock_list[(stock_list[\"ts_code\"] == stock_list[\"ts_code\"][cur_index])]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1946"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "times"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
